import React, {useState} from 'react';
import {Modal, Steps, Upload, message, Button, Form, Input, Select, Tree} from 'antd';
import {connect, Dispatch} from 'umi';
import {UploadOutlined} from '@ant-design/icons';
import * as XLSX from 'xlsx';

import {ConnectState, IResponse} from '@/models/connect';

interface UploadModelProps {
  dispatch: Dispatch;
  modalVisible: boolean;
  onCancel: () => void;
  loading?: boolean;
}

import styles from './style.less';

const UploadModel: React.FC<UploadModelProps> = (props) => {
  const {modalVisible, onCancel, dispatch, loading} = props;
  const [current, setCurrent] = useState<number>(1); // 步骤
  const [fileList, setFileList] = useState<Array<any>>([]); // 选择的文件列表
  const [readData, setReadData] = useState<any>(null); // 文件读取到的数据
  const [exelTitle, setExelTitle] = useState<Array<any>>([]); // 文件表头字段
  const [information, setInformation] = useState<any>({}); // 文件信息
  const [treeData, setTreeData] = useState<Array<any>>([]); // 文件数据展示
  const [filterDataArr, setfilterDataArr] = useState<Array<any>>([]); // 过滤后的文件数据
  const [form] = Form.useForm();
  const {validateFields} = form;

  // 前往下个步骤
  const nextCurrent = () => {
    // 上传数据
    if (current === 1) {
      validateFields().then(async (values) => {
        if (!readData) {
          message.warning('请导入正确数据');
          return;
        }
        if (
          (exelTitle.length > 2 && values.type === '1') ||
          (exelTitle.length === 2 && values.type === '2')
        ) {
          message.warning('导入文件的数据结构与选择类型不相符');
          return;
        }
        setInformation(values);
        setCurrent(2);
      });
    }

    // 选择字段
    if (current === 2) {
      for (let i = 0; i < exelTitle.length; i++) {
        if (!exelTitle[i].fieIndex) {
          message.warning('请完善字段定义');
          return;
        }
      }

      // 数据清洗，转换字段为后台定义字段
      const filterData: Array<any> = []; // 过滤后的数据
      readData.map((item: any) => {
        let filterObj = {};
        exelTitle.map((v: any) => {
          filterObj[v.fieIndex] = item[v.name];
        });
        filterData.push(filterObj);
      });

      // 树形结构
      let arr: Array<any> = [];
      if (information.type === '2') {
        filterData.map((item) => {
          arr.push({
            title: item.name,
            key: String(item.id),
            parent: item.parentId ? String(item.parentId) : item.parentId,
            longName: item.longPath
          });
        });
        const searchTreeById = (pId: any) => {
          const children = arr.filter(v => v.parent == pId)
          if (children) {
            children.map(v => {
              const children1 = searchTreeById(v.key)
              v.children = children1
              return v
            })
          }
          return children
        }

        arr = arr.filter((tree: any) => !tree.parent || tree.parent == '' || tree.parent == 'undefined').map((root) => {
          root.children = searchTreeById(root.key)
          return root;
        })

      } else {
        filterData.map((v) => {
          arr.push({
            title: v.name,
            key: String(v.id),
          });
        });
      }

      setfilterDataArr(filterData);
      setTreeData(arr);
      setCurrent(3);
    }

    // 展示数据结构
    if (current === 3) {

      const {name, no, type} = information;
      dispatch({
        type: 'dataRole/storageRoleData',
        payload: {dataRoleObjs: filterDataArr, name, no, type: Number(type)},
        callback: (response: IResponse) => {
          const {header} = response;
          if (header.code === 200) {
            message.success('存储成功');
            dispatch({
              type: 'dataRole/fetchRoleList',
            });
            onCancel()
          } else {
            message.warning('存储失败');
          }
        },
      });
    }
  };

  // 步骤点击切换
  const onChangeCurrent = (num: number) => {
    if (num < current - 1) {
      setCurrent(num + 1);
    }
  };

  // 数据导入解析
  const onImportExcel = (file: any) => {
    // 清除原本存在的解析数据
    setReadData(null);
    setExelTitle([]);

    let data: Array<any> = []; // 存储获取到的数据 // 通过FileReader对象读取文件

    const fileReader = new FileReader();

    fileReader.readAsBinaryString(file); //二进制
    fileReader.onload = (event: any) => {
      try {
        const {result} = event.target; // 以二进制流方式读取得到整份excel表格对象

        const workbook = XLSX.read(result, {type: 'binary'}); // 遍历每张工作表进行读取（这里默认只读取第一张表）
        for (const sheet in workbook.Sheets) {
          if (workbook.Sheets.hasOwnProperty(sheet)) {
            // 利用 sheet_to_json 方法将 excel 转成 json 数据

            data = data.concat(XLSX.utils.sheet_to_json(workbook.Sheets[sheet])); // break; // 如果只取第一张表，就取消注释这行
          }
        }
        if (data.length === 0) {
          message.warning('文件内容为空');
          return;
        }
        setReadData(data);
        // 获取表头字段
        if (data.length > 0) {
          const obj = data[data.length - 1];
          let arr = [];
          for (let key in obj) {
            const itemObj = {
              name: key,
              fieIndex: '',
            };
            switch (key) {
              case 'id':
                itemObj.fieIndex = 'id';
                break;
              case 'name':
                itemObj.fieIndex = 'name';
                break;
              case 'longPath':
                itemObj.fieIndex = 'longPath';
                break;
              case 'parentId':
                itemObj.fieIndex = 'parentId';
                break;
              default:
                break;
            }
            arr.push(itemObj);
          }
          setExelTitle(arr);
        }
      } catch (e) {
        // 这里可以抛出文件类型错误不正确的相关提示

        message.warning('文件类型不正确');

        return;
      }
    };
  };

  // 上传文件列表数量控制
  const handleFileChange = (info: any) => {
    const list = [...info.fileList];
    setFileList(list.slice(-1));
  };

  const handleTitleChange = (item: any, type: string) => {
    const newExelTitle = JSON.parse(JSON.stringify(exelTitle));
    newExelTitle.map((v: any) => {
      if (v.name === item.name) {
        v.fieIndex = type;
      }
    });
    setExelTitle(newExelTitle);
  };

  return (
    <Modal
      width={800}
      bodyStyle={{padding: '32px 0 0 0'}}
      destroyOnClose
      title="数据录入"
      visible={modalVisible}
      onCancel={() => onCancel()}
      footer={null}
    >
      <div className={styles.uploadModel}>
        <div className={styles.steps}>
          <Steps current={current - 1} onChange={onChangeCurrent}>
            <Steps.Step title="数据导入"/>
            <Steps.Step title="字段定义"/>
            <Steps.Step title="保存数据"/>
          </Steps>
        </div>

        {/* 步骤1，上传数据 */}
        {current === 1 ? (
          <div>
            <Form labelCol={{span: 4}} wrapperCol={{span: 14}} name="uploadForm" form={form}>
              <Form.Item label="唯一标识ID" name="no" rules={[{required: true}]}>
                <Input/>
              </Form.Item>
              <Form.Item label="名称" name="name" rules={[{required: true}]}>
                <Input/>
              </Form.Item>
              <Form.Item label="类型" name="type" rules={[{required: true}]}>
                <Select>
                  <Select.Option value="1">普通</Select.Option>
                  <Select.Option value="2">树形</Select.Option>
                </Select>
              </Form.Item>
              <Form.Item label="数据导入">
                <Upload
                  name="excel"
                  action=""
                  listType="text"
                  accept="file"
                  // @ts-ignore
                  beforeUpload={onImportExcel}
                  onChange={handleFileChange}
                  showUploadList={true}
                  fileList={fileList}
                >
                  <Button icon={<UploadOutlined/>}>点击上传</Button>
                </Upload>
              </Form.Item>
            </Form>

            <div className={styles.footerWrap}>
              <Button onClick={onCancel}>取消</Button>

              <Button type="primary" onClick={nextCurrent}>
                下一步
              </Button>
            </div>
          </div>
        ) : current === 2 ? (
          <div>
            <div style={{paddingLeft: '30px'}}>
              <Form labelCol={{span: 6}} wrapperCol={{span: 14}}>
                {exelTitle.map((item, key) => (
                  <Form.Item label={`Exel中的 ${item.name}`} key={key}>
                    {information.type === '2' ? (
                      <Select
                        defaultValue={item.fieIndex}
                        onChange={(type) => {
                          handleTitleChange(item, type);
                        }}
                      >
                        <Select.Option value="id">业务ID</Select.Option>
                        <Select.Option value="name">业务名称</Select.Option>
                        <Select.Option value="longPath">长路径</Select.Option>
                        <Select.Option value="parentId">父ID</Select.Option>
                      </Select>
                    ) : (
                      <Select
                        defaultValue={item.fieIndex}
                        onChange={(type) => {
                          handleTitleChange(item, type);
                        }}
                      >
                        <Select.Option value="id">业务ID</Select.Option>
                        <Select.Option value="name">业务名称</Select.Option>
                      </Select>
                    )}
                  </Form.Item>
                ))}
              </Form>
            </div>

            <div className={styles.footerWrap}>
              <Button onClick={onCancel}>取消</Button>

              <Button type="primary" onClick={nextCurrent}>
                下一步
              </Button>
            </div>
          </div>
        ) : (
          <div>
            <div style={{paddingLeft: '30px'}}>
              <Tree treeData={treeData}/>
            </div>

            <div className={styles.footerWrap}>
              <Button onClick={onCancel}>取消</Button>

              <Button type="primary" onClick={nextCurrent} loading={loading}>
                存储
              </Button>
            </div>
          </div>
        )}
      </div>
    </Modal>
  );
};

export default connect(({loading}: ConnectState) => ({
  loading: loading.effects['panel/fetchDashboard'],
}))(UploadModel);
